package com.lc1993929.shiro.bean;

import com.lc1993929.shiro.mapper.AccountMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.*;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by LiuChang on 2017/5/18.
 * Realm    需要查询数据库，并且得到正确的数据
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private AccountMapper accountMapper;

    /**
     * 1、doGetAuthenticationInfo    获取认证消息，如果数据库中没有数据，返回null，如果得到正确的用户名和密码，返回指定类型的对象
     * 2、AuthenticationInfo     可以使用SimpleAuthenticationInfo实现类，封装正确的用户名和密码
     * 3、authenticationToken   就是我们需要认证的token
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("the first realm is working!!!");

        SimpleAuthenticationInfo info = null;
        //1、将token转换成UserPasswordToken
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        //2、获取用户名即可
        String username = usernamePasswordToken.getUsername();
        //3、查询数据库,是否存在指定用户名和密码的用户
        Account account = accountMapper.getAccountByName(username);
        if (account != null) {
            //4、如果查询到了，封装查询结果，返回给我们的调用
            Object principal = username;
            Object credentials = account.getPassword();
            String realmName = this.getName();
            ByteSource salt = ByteSource.Util.bytes(username);

            SimpleHash simpleHash = new SimpleHash("MD5", credentials, salt, 1024);

            //info = new SimpleAuthenticationInfo(principal, simpleHash, realmName);
            info = new SimpleAuthenticationInfo(principal, simpleHash, salt, realmName);
        } else {
            //5、如果没有查询到，抛出一个异常
            throw new AuthenticationException();
        }

        return info;
    }

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //返回值：AuthorizationInfo     封装获取的用户对应的所有角色，SimpleAuthorizationInfo（Set<string>)
        //参数列表：PrincipalCollection      登陆的身份，登陆的用户名

        SimpleAuthorizationInfo info = null;
        String username = principalCollection.toString();

        Account account = accountMapper.getAccountByName(username);
        if (account != null) {
            //4、如果查询到了，封装查询结果，返回给我们的调用
            Object principal = username;
            Object credentials = account.getPassword();
            String realmName = this.getName();
            ByteSource salt = ByteSource.Util.bytes(username);

            SimpleHash simpleHash = new SimpleHash("MD5", credentials, salt, 1024);

            Set<String> roles = new HashSet<String>();
            roles.add(account.getRoles());
            info = new SimpleAuthorizationInfo(roles);
        } else {
            //5、如果没有查询到，抛出一个异常
            throw new AuthorizationException();
        }
        return info;
    }
}
